package com.wpw.dream.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class NIOServer {
	
	private ServerSocketChannel server;
	
	private Selector selector;
	
	private ByteBuffer recBuffer;
	
	private ByteBuffer sendBuffer;
	
	Map<SelectionKey, String> map = new HashMap<>();
	
	public NIOServer(int port) {
		try {
			server = ServerSocketChannel.open();
			server.configureBlocking(false);
			server.socket().bind(new InetSocketAddress(port));
			selector = Selector.open();
			server.register(selector, SelectionKey.OP_ACCEPT);
			
			recBuffer = ByteBuffer.allocate(1024);
			sendBuffer = ByteBuffer.allocate(1024);
			
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public void listen() {
		try {
			while (true) {
				int count = selector.select();
				if (count == 0) {
					continue;
				}
				Set<SelectionKey> keys = selector.selectedKeys();
				Iterator<SelectionKey> iterator = keys.iterator();
				while (iterator.hasNext()) {
					SelectionKey next = iterator.next();
					
					process(next);

					iterator.remove();
				}
			}
			
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private void process(SelectionKey key) {
		SocketChannel client = null;
		
		try {
			if (key.isValid() && key.isAcceptable()) {
				client = server.accept();
				client.configureBlocking(false);
				client.register(selector, SelectionKey.OP_READ);
			} else if (key.isValid() && key.isReadable()) {
				client = (SocketChannel) key.channel();//server.accept();
				client.configureBlocking(false);
				
				recBuffer.clear();
				
				int len = client.read(recBuffer);
				if (len != 0) {
					String msg = new String(recBuffer.array(), 0, len);
					map.put(key, msg);
					System.out.println("收到消息：" + msg);
				}
				
				client.register(selector, SelectionKey.OP_WRITE);
				
			} else if (key.isValid() && key.isWritable()) {
				if (map.get(key) == null) {
					return;
				}
				client = (SocketChannel) key.channel();//server.accept();
				client.configureBlocking(false);
				sendBuffer.clear();
				sendBuffer.put(new String(map.get(key) + "您好,收到请求").getBytes());
				sendBuffer.flip();
				client.write(sendBuffer);
				
				client.register(selector, SelectionKey.OP_READ);
				
			}
		} catch (IOException e) {
			e.printStackTrace();
			try {
				if (client != null) {
					client.close();
				}
				server.close();
				selector.close();
			} catch (IOException e1) {
				e1.printStackTrace();
			}
		}
	}
	
	public static void main(String[] args) {
		new NIOServer(8091).listen();
	}
}
